package xm.com.handlertest;

import android.os.Build;
import android.support.annotation.RequiresApi;

import java.util.concurrent.LinkedTransferQueue;


public class TestThreadMsg5 {
    public static Handler mainHandler;

    public static void main(String[] args){
        Looper.prepare();

        mainHandler = new Handler(new Handler.Callback() {
            @Override
            public boolean handleMessage(Message msg) {
                System.out.println("主线程:"+Thread.currentThread().getId()+"  收到消息:"+msg.obj);
                if (msg.what == 1){
                    System.out.println("主线程:"+Thread.currentThread().getId()+"  do work!");
                    System.out.println("");
                    System.out.println("");
                }
                return false;
            }
        });

        Thread1 t1 = new Thread1();
        t1.start();

        Looper.loop();//阻塞式,死循环遍历消息列表
    }

    /**
     * 模拟Handler，主要职责:
     *   1.把消息放入到线程对应的Looper对象的消息队列里
     *   2.处理消息
     * Handler就是一个线程处理消息的钩子或者叫句柄，一个线程可以有很多个Handler实例
     * 所以每个Message对象都有个target，指明消息对象由哪个Handler进行处理
     * 而每个线程只允许有一个Looper对象与之对应,只有一个Looper对象自然也就只有一个消息队列了。
     *
     */
    public static class Handler {
        Looper mLooper = null;
        LinkedTransferQueue mQueue = null;
        Callback mCallback = null;

        //回调接口
        public interface Callback {
            public boolean handleMessage(Message msg);
        }

        public Handler(Callback callback) {
            this.mLooper = Looper.myLooper();
            this.mQueue = mLooper.mQueue;
            this.mCallback = callback;
        }

        public void dispatchMessage(Message msg){
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
        }

        public final void sendMessage(Message msg){
            msg.target = this;
            mQueue.put(msg);
        }
    }

    /**
     * 消息实体类,主要职责:
     *  1.承载消息内容
     *  2.指定由谁来处理我(消息)
     */
    static class Message {
        public int what;
        public Object obj;
        public Handler target;//消息对应的Handler
    }

    /**
     * 模拟Looper，主要职责:
     *  1.创建管理消息队列
     *  2.不断死循环取出消息队列里的消息
     *  3.处理消息（后续交给Handler处理）
     *  说明：Looper用静态prepare()方法实例化自己，每个线程只能实例化一个Looper对象
     *  Looper的myLooper()方法，在哪个线程调用就返回哪个线程的Looper对象(通过ThreadLocal实现)
     */
    static class Looper{
        //ThreadLocal用于保存某个线程共享变量:对于同一个static ThreadLocal,不同线程只能从中get,set,remove自己的变量,而不会影响其他线程的变量
        static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
        LinkedTransferQueue mQueue;//阻塞式消息队列,每一个线程对应一个消息队列

        private Looper(){
            this.mQueue = new LinkedTransferQueue();//初始化阻塞式消息队列
        }

        /**
         * 初始化Looper,并放到线程变量里,
         * 这里做了限制，每个线程只能有一个Looper对象,因为是死循环多个也无意义
         */
        public static void prepare() {
            if (sThreadLocal.get() != null) {
                throw new RuntimeException("Only one Looper may be created per thread");
            }
            sThreadLocal.set(new Looper());
        }

        /**
         * 从线程变量里取出,当前线程对应的Looper
         * @return
         */
        public static Looper myLooper() {
            return sThreadLocal.get();
        }

        /**
         * 取出当前线程里的Looperd对象开始死循环遍历消息队列
         */
        public static void loop(){
            final Looper me = myLooper();
            //模拟LOOP的循环方法
            for (;;) {
                Message msg = null;
                try {
                    msg = (Message) me.mQueue.take();
                    msg.target.dispatchMessage(msg);//交个Message指定的Handler去处理
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        public LinkedTransferQueue getQueue() {
            return mQueue;
        }
    }


    static class Thread1 extends Thread{
        @Override
        public void run() {
            super.run();
            for (;;) {
                try {
                    Message msg = new Message();
                    msg.what = 1;
                    msg.obj = "主线程去更新UI吧";
                    System.out.println("子线程:"+Thread.currentThread().getId()+"  发送消息:"+msg.obj);
                    mainHandler.sendMessage(msg);//向主线程的Looper的消息队列里添加消息
                    Thread.sleep(5000);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

}
